package com.wang.diaryauth.service.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.wang.diaryauth.domain.User;
import com.wang.diaryauth.domain.UserRoleRel;
import com.wang.diaryauth.enums.LoginTypeEnum;
import com.wang.diaryauth.enums.ResponseCodeEnum;
import com.wang.diaryauth.mapper.UserMapper;
import com.wang.diaryauth.mapper.UserRoleRelMapper;
import com.wang.diaryauth.model.vo.user.UserLoginVO;
import com.wang.diaryauth.service.UserService;
import com.wang.framework.common.constant.RedisKeyConstants;
import com.wang.framework.common.constant.RoleConstants;
import com.wang.framework.common.enums.DeletedEnum;
import com.wang.framework.common.enums.StatusEnum;
import com.wang.framework.common.exception.BizException;
import com.wang.framework.common.response.Response;
import com.wang.framework.common.util.JsonUtils;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
* @author wangs
* @description 针对表【t_user(用户表)】的数据库操作Service实现
* @createDate 2024-10-28 10:12:25
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserRoleRelMapper userRoleRelMapper;

    @Resource
    private RedisTemplate<String,Object> redisTemplate;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Override
    public Response<String> loginAndRegister(UserLoginVO userLoginVO) {
        Integer type = userLoginVO.getType();
        String phone = userLoginVO.getPhone();

        LoginTypeEnum loginTypeEnum = LoginTypeEnum.valueOf(type);

        Long userId = null;

        switch (Objects.requireNonNull(loginTypeEnum)){
            case VERIFICATION_CODE -> {
                String reqCode = userLoginVO.getCode();
                // 校验入参验证码是否为空
                Preconditions.checkArgument(StringUtils.isNotBlank(reqCode), "验证码不能为空");


                String key = RedisKeyConstants.buildVerificationCodeKey(phone);
                String code = (String)redisTemplate.opsForValue().get(key);

                if (!reqCode.equals(code)) {
                    throw new BizException(ResponseCodeEnum.PARAM_NOT_VALID);
                }

                User user = userMapper.selectByPhoneUser(phone);

                if (Objects.isNull(user)) {
                    // 注册用户
                    userId = registerUser(phone);
                }else {
                    userId = user.getId();
                }

            }
            case PASSWORD -> {

            }
            default -> {

            }
        }
        // SaToken 登录用户, 入参为用户 ID
        StpUtil.login(userId);

        // 获取 Token 令牌
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();

        // 返回 Token 令牌
        return Response.success(tokenInfo.tokenValue);
    }

    @Transactional(rollbackFor = Exception.class)
    public Long registerUser(String phone) {

        return transactionTemplate.execute(status -> {
            Long increment = redisTemplate.opsForValue().increment(RedisKeyConstants.XIAOHASHU_ID_GENERATOR_KEY);

            User user = User.builder()
                    .phone(phone)
                    .xiaohashuId(String.valueOf(increment))
                    .nickname("小红薯" + increment)
                    .status(StatusEnum.ENABLE.getValue())
                    .isDeleted(DeletedEnum.NO.getValue())
                    .createTime(LocalDateTime.now())
                    .updateTime(LocalDateTime.now())
                    .build();
            userMapper.insert(user);

            Long userId = user.getId();

            UserRoleRel userRoleRel = UserRoleRel.builder()
                    .userId(userId)
                    .roleId(RoleConstants.COMMON_USER_ROLE_ID)
                    .isDeleted(DeletedEnum.NO.getValue())
                    .createTime(LocalDateTime.now())
                    .updateTime(LocalDateTime.now())
                    .build();
            userRoleRelMapper.insert(userRoleRel);

            // 将该用户的角色 ID 存入 Redis 中
            List<Long> roles = Lists.newArrayList();
            roles.add(RoleConstants.COMMON_USER_ROLE_ID);
            String userRolesKey = RedisKeyConstants.buildUserRoleKey(phone);
            redisTemplate.opsForValue().set(userRolesKey, JsonUtils.toJsonString(roles));


            return userId;

        });
    }
}




